/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+#define _GNU_SOURCE
+
#include "config.h"
#if defined (HAVE_MALLINFO) || defined (HAVE_MALLINFO2)
#include <link.h>
#ifdef HAVE_EXE_INTROSPECTION
+#include <dlfcn.h>
#include <elf.h>
#endif
g_auto (GStrv) paths = NULL;
g_autofree char *exe_dir = NULL;
GStrv str;
+ Dl_info dl_info;
+ struct link_map *link_map = NULL;
for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; dyn++)
{
if ((!rpath && !runpath) || !strtab)
return;
+ if (dladdr1 (_DYNAMIC, &dl_info, (void **) &link_map, RTLD_DL_LINKMAP))
+ {
+ /* Sanity check */
+ g_return_if_fail ((void *) _DYNAMIC == (void *) link_map->l_ld);
+
+ /* strtab should be at an offset above our load address. If it's not
+ * then this is a special architecture (riscv, mips) that has a
+ * readonly _DYNAMIC section that's not relocated. So in that case
+ * strtab is currently an offset rather than an address. Let's make it
+ * an address...
+ */
+ if (strtab < (const char *) link_map->l_addr)
+ strtab += link_map->l_addr;
+ }
+
if (rpath)
paths = g_strsplit (strtab + rpath->d_un.d_val, ":", -1);
else